﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.IO;

namespace AramaruForest
{
    struct TextPopup
    {
        public int X;
        public int Y;
        public string Text;

        public TextPopup(int x, int y, string text)
        {
            X = x;
            Y = y;
            Text = text;
        }
    }

    internal class World
    {
        public GameState _gameState;
        
        public GameItems _gameItems;
        public SizeF WorldLimits;
        public SizeF Camera;
        public PointF CameraLocation;
        public bool Wizard;
        public int mana;
        public int manaIterator;
        public double _gameTime;
        public int level;
        public int hp;

        private List<TextPopup> _popups = new List<TextPopup>();

        private static Font _font = new Font("Arial", 18);
        private static Brush _whiteBrush = new SolidBrush(Color.White);
        private static Brush _blackBrush = new SolidBrush(Color.Red);

        

        public World(GameState gamestate)
        {
            _gameState = gamestate;
            level = 1;
            mana = 10;
            hp = 6;
            Initialize();
        }

        public void Update(double gameTime, double elapsedTime)
        {
            if (mana > 10)
                mana = 10;
            hp = _gameItems.Hero.Hp;
            if (_gameItems.Hero.Hp <= 0)
            {
                foreach (Sprite tile in _gameItems.Area)
                {
                    if (tile.message != null)
                        _gameState._messageCount--;
                }
                Initialize();
            }
            foreach (Sprite i in _gameItems.Area)
            {
                if (Sprite.Collision(i, _gameItems.Hero) && i.win)
                {
                    level++;
                    Initialize();
                }
            }

            _gameItems.Update(gameTime, elapsedTime);
            _gameTime = gameTime;

            CameraLocation.X = _gameItems.Hero.Location.X - Camera.Width / 2;
            CameraLocation.Y = _gameItems.Hero.Location.Y - Camera.Height / 2;

            if (CameraLocation.X + Camera.Width > WorldLimits.Width)
                CameraLocation.X = WorldLimits.Width - Camera.Width;
            if (CameraLocation.X < 0)
                CameraLocation.X = 0;

            if (CameraLocation.Y + Camera.Height > WorldLimits.Height)
                CameraLocation.Y = WorldLimits.Height - Camera.Height;
            if (CameraLocation.Y < 0)
                CameraLocation.Y = 0;

            if (mana < 30 && Wizard)
            {
                if (manaIterator >= 10)
                {
                    mana++;
                    manaIterator = 0;
                }
                else
                    manaIterator++;
            }

        }

        public void Draw(Graphics graphics)
        {
            _gameItems.Draw(graphics);

            //Sprite hpla = Generator.GenerateHpLabel(_gameState, 0 + (int)CameraLocation.X, (int)CameraLocation.Y);
            //hpla.Draw(graphics);

            for(int i = _gameItems.Hero.Hp; i > 0; i--)
            {
                Sprite hp = Generator.GenerateHp(_gameState, 15 * (i-1) + (int)CameraLocation.X, (int)CameraLocation.Y);
                hp.Draw(graphics);
            }
            if (Wizard)
            {
                for (int i = mana; i > 0; i--)
                {
                    Sprite manas = Generator.GenerateMana(_gameState, 1 * i + (int)CameraLocation.X, (int)CameraLocation.Y + 30);
                    manas.Draw(graphics);
                }
            }
            else
                for (int i = mana; i > 0; i--)
                {
                    Sprite manas = Generator.GenerateUpKunai(_gameState, 8 * (i-1) + (int)CameraLocation.X, (int)CameraLocation.Y + 30);
                    manas.Draw(graphics);
                }

            foreach (TextPopup popup in _popups)
            {
                // Draw 4 text offsets to get an outline
                graphics.DrawString(popup.Text, _font, _whiteBrush, popup.X + 2, popup.Y);
                graphics.DrawString(popup.Text, _font, _whiteBrush, popup.X - 1, popup.Y);
                graphics.DrawString(popup.Text, _font, _whiteBrush, popup.X, popup.Y + 2);
                graphics.DrawString(popup.Text, _font, _whiteBrush, popup.X, popup.Y - 2);

                // Draw the actual text
                graphics.DrawString(popup.Text, _font, _blackBrush, popup.X, popup.Y);
            }

        }


        public void Initialize()
        {
            //Wizard = true;

            if (hp <= 0)
                hp = 6;
            
            
            manaIterator = 0;
            _gameItems = new GameItems(_gameState);
            _gameItems.Hero = Generator.GenerateHero(_gameState, 200, 90);
            _gameItems.Hero.Hp = hp;
            CreateTestEnviroment();

            Camera = _gameState.GameSize;
            
            CameraLocation = new PointF(0, Camera.Height);

            
                
            
        }

       

        private void CreateTestEnviroment()
        {
            WorldLimits = Camera;

            if (level != 3)
                _gameItems.Area.Add(new Sprite(_gameState, 0, WorldLimits.Height - 798, @"Data\GenericBackground.bmp", new Rectangle(new Point(0, 0), new Size(3192, 591)), 1));
            else
                _gameItems.Area.Add(new Sprite(_gameState, 0, WorldLimits.Height - 499, @"Data\ColumnBackground.bmp", new Rectangle(new Point(0, 0), new Size(798, 2856)), 1));


            _gameItems.Area[0].ColorKey = Color.FromArgb(75, 75, 75);

            
            ReadFile();

            _gameItems.Area[0].Location.Y = WorldLimits.Height;
           
            
           

        }

        

        private void ReadFile()
        {
            string lv = level.ToString();
            try
            {
                StreamReader akjgh = new StreamReader(@"Data\Level" + lv + @".txt");
            }
            catch
            {
                level = 1;
                lv = level.ToString();
                _gameState._messageCount = 0;
            }
            StreamReader r = new StreamReader(@"Data\Level" + lv + @".txt");
            int rows = 0;
            int columns = 0;

            while (!r.EndOfStream)
            {
                r.ReadLine();
                rows++;
            }
            WorldLimits.Height = rows * 50;
            r.Close();

            StreamReader l = new StreamReader(@"Data\Level" + lv + @".txt");
            string sdata = l.ReadToEnd();
            l.Close();

            columns = sdata.Length / rows;

            List<string> ldata = new List<string>();
            StreamReader p = new StreamReader(@"Data\Level" + lv + @".txt");
            while (!p.EndOfStream)
            {
                ldata.Add(p.ReadLine());
            }

            char[][] grid = new char[ldata.Count][];

            for (int i = 0; i < ldata.Count; i++)
            {
                grid[i] = ldata[i].ToCharArray();
            }

            int rowcounter = 0;
            int columncounter = 0;
            int rowcounter2 = 1;
            int columncounter2 = 0;
             
            foreach (char[] s in grid)
            {
                foreach(char c in s)
                {
                    Parse(grid[rowcounter][columncounter], columncounter2 * 50, rowcounter2 * 50);
                    columncounter++;
                    columncounter2++;
                }
                columncounter = 0;
                rowcounter++;
                columncounter2 = 0;
                rowcounter2++;
            }


            WorldLimits.Height = grid.Count() * 50;
            WorldLimits.Width = grid[0].Count() * 50;
            
        }

        public void Parse(char character, int x, int y)
        {
            

            switch (character)
            {
                case'b':
                    _gameItems.Area.Add(Generator.GenerateBlock(_gameState, x, y));
                    break;
                case 'g':
                    _gameItems.Enemies.Add(Generator.GenerateGoblin(_gameState, x, y + 24));
                    break;
                case 'i':
                    _gameItems.Enemies.Add(Generator.GenerateBird(_gameState, x, y));
                    break;
                case 'p':
                    _gameItems.Items.Add(Generator.GeneratePotion1(_gameState, x + 2, y + 1));
                    break;
                case 'o':
                    _gameItems.Enemies.Add(Generator.GenerateOger(_gameState, x, y + 1));
                    break;
                case 'P':
                    _gameItems.Enemies.Add(Generator.GeneratePhantom(_gameState, x, y));
                    break;
                case 'k':
                    _gameItems.Items.Add(Generator.GeneratePickUpKunai(_gameState, x + 2, y + 41));
                    break;
                case 'w':
                    _gameItems.Area.Add(Generator.GenerateWin(_gameState, x, y));
                    break;
                case 's':
                    _gameItems.Enemies.Add(Generator.GenerateSpikes(_gameState, x, y + 35));
                    break;
                case 'S':
                    _gameItems.Enemies.Add(Generator.GenerateSorcerer(_gameState, x, y + 1));
                    break;
                case 'z':
                    _gameItems.Enemies.Add(Generator.GenerateSorcererBoss(_gameState, x, y + 1));
                    break;
                case 't':
                    _gameItems.Area.Add(Generator.GenerateKunaiTrap(_gameState, x, y));
                    break;
                case 'r':
                    _gameItems.Area.Add(Generator.GenerateSpikesTrap(_gameState, x, y));
                    break;
                case 'f':
                    _gameItems.Area.Add(Generator.GenerateFallingBlockTrap(_gameState, x, y));
                    break;
                case 'm':
                    _gameItems.Area.Add(Generator.GenerateMonument(_gameState, x, y));
                    break;
                
                
                case 'h':
                    _gameItems.Hero.Location.X = x;
                    _gameItems.Hero.Location.Y = y + 1;
                    break;

                default:
                    break;
            }

            
        }

       

        public void KeyDown(Keys keys)
        {
            _popups.Clear();
            if (_gameItems.Hero.Hp <= 0)
            {
                //Initialize();
                //return;
            }

            switch (keys)
            {
                case Keys.Up:
                    _gameItems.Hero.Airborn = !_gameItems.Hero.OnGround();
                    if (!_gameItems.Hero.Airborn || _gameItems.Hero.Location.Y + _gameItems.Hero.Size.Height >= WorldLimits.Height)
                    {
                        _gameItems.Hero.Location.Y -= 1;
                        _gameItems.Hero.JumpForce = 220;
                        _gameItems.Hero.JumpStart = _gameTime;
                    }
                    break;

                case Keys.Down:
                    break;

                case Keys.Q:
                    //level++;
                    //Initialize();
                    break;

                case Keys.Right:
                    _gameItems.Hero.Flip = false;
                    _gameItems.Hero.Velocity.X = 80;
                    break;

                case Keys.Left:
                    _gameItems.Hero.Flip = true;
                    _gameItems.Hero.Velocity.X = -80;
                    break;

                case Keys.Space:
                    if (_gameItems.Hero.AttackTime == 0)
                    {
                        _gameItems.Projectiles.RemoveAll(_gameItems.GetWeapons);
                        _gameItems.Hero.AttackTime = 7;
                        _gameItems.Hero.Velocity.X = 0;
                        _gameItems.Projectiles.Add(Generator.GenerateUpKunai(_gameState, (int)_gameItems.Hero.Location.X + (int)_gameItems.Hero.Size.Width / 2, (int)_gameItems.Hero.Location.Y - 10));
                        _gameItems.Projectiles[_gameItems.Projectiles.Count() - 1].HeroItem = true;
                        _gameItems.Projectiles[_gameItems.Projectiles.Count() - 1].gravity = false;
                        _gameItems.Projectiles[_gameItems.Projectiles.Count() - 1].DownFlip = false;
                        _gameItems.Projectiles[_gameItems.Projectiles.Count() - 1].attack = 3;
                        _gameItems.Hero.attackingClose = true;
                    }
                    break;

                case Keys.D:
                    
                    if(mana > 0)
                    {
                        Sprite kunai = Generator.GenerateKunai(_gameState, (int)_gameItems.Hero.Location.X + (int)_gameItems.Hero.Size.Width, (int)_gameItems.Hero.Location.Y + (int)_gameItems.Hero.Size.Height / 2, _gameItems.Hero.Flip);
                        _gameItems.Hero.AttackTime = 10;
                        if (_gameItems.Hero.Flip)
                            kunai.Velocity.X = -300;
                        else
                            kunai.Velocity.X = 300;
                        _gameItems.Projectiles.Add(kunai);
                        mana--;
                    }
                    
                    break;

                case Keys.W:
                     if (mana > 0)
                    {
                        Sprite kunai = Generator.GenerateUpKunai(_gameState, (int)_gameItems.Hero.Location.X + (int)_gameItems.Hero.Size.Width / 2, (int)_gameItems.Hero.Location.Y - 15);
                        _gameItems.Hero.AttackTime = 10;
                        kunai.JumpStart = _gameTime;
                        kunai.JumpForce = 300 - _gameItems.Hero.Velocity.Y / 2;
                        _gameItems.Hero.attackingUp = true;
                        _gameItems.Projectiles.Add(kunai);
                        mana--;
                    }
                    
                    break;

                case Keys.S:
                    break;

                case Keys.A:
                    if (Wizard)
                    {
                        //Sprite kunai = Generator.GenerateWave(_gameState, (int)_gameItems.Hero.Location.X + (int)_gameItems.Hero.Size.Width - 1, (int)_gameItems.Hero.Location.Y + (int)_gameItems.Hero.Size.Height / 2, _gameItems.Hero.Flip);
                        //_gameItems.Hero.AttackTime = 10;
                        //if (_gameItems.Hero.Flip)
                        //    kunai.Velocity.X = 200;
                        //else
                        //    kunai.Velocity.X = -200;
                        //_gameItems.Projectiles.Add(kunai);
                    }
                    else if (mana > 0)
                    {
                        Sprite kunai = Generator.GenerateCaltrop(_gameState, (int)_gameItems.Hero.Location.X + (int)_gameItems.Hero.Size.Width - 1, (int)_gameItems.Hero.Location.Y + (int)_gameItems.Hero.Size.Height / 2, _gameItems.Hero.Flip);
                        _gameItems.Hero.AttackTime = 10;
                        _gameItems.Hero.attackingUp = true;
                        _gameItems.Projectiles.Add(kunai);
                        mana--;
                    }
                    break;

                case Keys.N:
                    foreach (Sprite m in _gameItems.Area)
                    {
                        if (m.message != null && Sprite.Collision(m, _gameItems.Hero))
                        {
                            _popups.Add(new TextPopup(50, 80, m.message));
                            break;
                        }
                    }
                    break;

                default:
                    break;
            }
        }

    }
}
